Skip to content

fix(ci): eval canary must run as public-owner sentinel, not E2E user#383

Merged
BigSimmo merged 1 commit into
mainfrom
claude/fable-repo-tasks-nseked
Jul 8, 2026
Merged

fix(ci): eval canary must run as public-owner sentinel, not E2E user#383
BigSimmo merged 1 commit into
mainfrom
claude/fable-repo-tasks-nseked

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

The nightly Eval Canary has failed every run since it was created (runs #1#3: two scheduled, one workflow_dispatch). This PR fixes one of the two reasons.

Diagnosed from run #3's job log (85793690941): secrets preflight ✅ → check:supabase-project ✅ → golden retrieval eval fails in ~2s. Two independent problems:

  1. Owner mis-scoping (fixed here). The workflow pinned the eval owner via RAG_EVAL_OWNER_EMAIL: ${{ secrets.E2E_USER_EMAIL }}. The live corpus went all-public (owner_id = NULL), so that user owns 0 retrievable documents → 0 candidates → --fail-on-threshold trips. resolveEvalOwnerId (scripts/eval-utils.ts) already defaults to the public-owner sentinel 00000000-…-0000 when no owner is set. This PR drops the owner pin so the canary inherits that sentinel, and removes the now-unused E2E_USER_EMAIL from the required-secrets preflight.

  2. Stale OpenAI secret (operator action — NOT in this PR). The actual current red is Unregistered API key at the embedding step, i.e. a stale/revoked OPENAI_API_KEY repo secret (consistent with the documented Jul 5–6 key rotations that were never propagated to Actions secrets). Rotating that secret is an operator action I can't perform. Until it is rotated the canary stays red; with both addressed it should pass in one run.

Why this matters: a guard that is red every night for an infra reason can't signal a real regression — it masks exactly the silent-degradation failure mode the canary exists to catch.

Verification

  • npx prettier --check .github/workflows/eval-canary.yml — passes
  • Change is limited to .github/workflows/eval-canary.yml (env pin removed + preflight line removed; explanatory comment added)
  • Confirmed precedence in scripts/eval-utils.ts: ownerId ?? (ownerEmail → lookup) ?? DEFAULT_EVAL_OWNER_ID — removing the email override falls through to the public sentinel
  • Operator: rotate the OPENAI_API_KEY repo secret to the current valid key, then trigger one workflow_dispatch run and confirm green before trusting the nightly cadence

Offline health snapshot of main (Node 24.18.0, separate from this change): lint 0 errors / 11 pre-existing warnings, typecheck clean, test 1317 passed / 3 skipped / 0 failed.

Clinical Governance Preflight

CI-only change to a scheduled eval workflow. No ingestion, answer-generation, retrieval, ranking, source-rendering, privacy, or production-env behavior is touched.

  • No clinical decision-support behavior changed
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy)
  • Service-role keys / secrets remain server-side (GitHub Actions secrets); none exposed
  • No document-access or owner-scope logic changed (this only selects which owner the eval reads as)

Notes

  • Follow-up (optional): the workflow's secrets preflight checks presence but not validity, which is why a stale-but-present OPENAI_API_KEY passed preflight and failed at the embedding call. A lightweight key-validity probe before the eval step would surface this as a clear preflight error instead of a mid-eval failure.

🤖 Generated with Claude Code

https://claude.ai/code/session_01R5KT4sYGB8TGQ4jV888EPH


Generated by Claude Code

The nightly eval canary pinned the eval owner to the E2E user via
RAG_EVAL_OWNER_EMAIL. Since the corpus went all-public (owner_id = NULL),
that user owns 0 retrievable documents, so the golden retrieval eval
returns 0 candidates and fails --fail-on-threshold every run.

resolveEvalOwnerId (scripts/eval-utils.ts) already defaults to the
public-owner sentinel 00000000-0000-0000-0000-000000000000 when no owner
is set (the fix established in the eval-owner-default change). Drop the
owner pin so the canary inherits that sentinel and scopes to the public
corpus, and remove the now-unused E2E_USER_EMAIL from the required-secrets
preflight.

Note: this removes the *owner* failure only. The canary's current red is a
stale/unregistered OPENAI_API_KEY repo secret ("Unregistered API key" at
the embedding step); rotating that secret is an operator action. With both
addressed the canary should pass in one run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5KT4sYGB8TGQ4jV888EPH
@supabase

supabase Bot commented Jul 8, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@BigSimmo
BigSimmo marked this pull request as ready for review July 8, 2026 07:57
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@BigSimmo
BigSimmo merged commit fd03b05 into main Jul 8, 2026
5 checks passed
@BigSimmo
BigSimmo deleted the claude/fable-repo-tasks-nseked branch July 8, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants